import tushare as ts
import pandas as pd
import numpy as np
import os
import sys

'''
DataFrame.sort_values(by, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last')
axis：{0 or ‘index’, 1 or ‘columns’}, default 0，默认按照列排序，即纵向排序；如果为1，则是横向排序。
by：str or list of str；如果axis=0，那么by="列名"；如果axis=1，那么by="行名"。
ascending：布尔型，True则升序，如果by=['列名1','列名2']，则该参数可以是[True, False]，即第一字段升序，第二个降序。
inplace：布尔型，是否用排序后的数据框替换现有的数据框。
kind：排序方法，{‘quicksort’, ‘mergesort’, ‘heapsort’}, default ‘quicksort’。似乎不用太关心。
na_position：{‘first’, ‘last’}, default ‘last’，默认缺失值排在最后面。
'''

# 分别计算 60 30 20 10 5 天的对应排名
# (聚宽)market_cap 总市值 & (数据表)total_cap


'''
策略一：   升序
根据板块的每日排名，往前 n 天对排名成绩，计数相应分数(分数即为对应当天的排名)
最后根据 N 日的分数之和的对应的代码，低到高排序 (优先选取分数低的股票)
分数相同按照市值排序(后处理)
'''
# 单独取出 一个时间序列，存放起来
# print(df_bksj)
"""
    df.query（expr，inplace = False，** kwargs ）# 使用布尔表达式查询帧的列

    参数：
    # expr：str要评估的查询字符串。你可以在环境中引用变量，在它们前面添加一个'@'字符 。@a + b
    # inplace=False：是否修改数据或返回副本
    # kwargs：dict关键字参数

    返回：DataFrame
    """


def policy1_score():
    # 板块数据
    df_bksj = pd.read_csv("D:/硕士研究/毕业设计准备/股票代码及处理/模块排序处理/model_info.csv", encoding="utf-8")
    df_bksj_demo = pd.read_csv("D:/硕士研究/毕业设计准备/股票代码及处理/模块排序处理/model_info_demo.csv", encoding="utf-8")

    # 板块 详细信息
    df_industry = pd.read_csv("D:/硕士研究/毕业设计准备/股票代码及处理/模块排序处理/industry_info.csv", encoding="utf-8")
    df_industry = df_industry.drop(labels=['parent_id'], axis=1)

    df_combine = pd.merge(df_bksj, df_industry, how='inner', left_on='bkdm', right_on='industry_id')
    df_combine = df_combine.drop(labels=['industry_id', 'type'], axis=1)
    # 股票基本信息
    # df_stock_base = pd.read_csv("D:/硕士研究/毕业设计准备/前复权日线+指标(第一次数据)/A股基础信息.csv", encoding="utf-8")

    # pd.set_option('display.max_columns', None)   显示所有的行，不省略

    # 股票日线信息  只要 三个字段，排序总市值最后使用的数据
    # df_daily = pd.read_csv("all_in_one.csv", encoding="utf-8")
    # daily_order = ["ts_code", "trade_date", "总市值 （万元）"]
    # df_daily = df_daily[daily_order]
    # 读取 -------------------------------------------------------

    # 分数列  存放计分
    df_combine['score'] = 0
    # df_time = df_bksj_demo.query('bkdm==880201')['sj']

    # 转换 时间格式
    df_combine['sj'] = pd.to_datetime(df_combine['sj'], format='%Y%m%d')
    # 保留time 关联
    df_combine['time'] = df_combine['sj']
    # sj 转为 索引
    df_combine.set_index(['sj'], inplace=True)

    # -----------------进入60 30 20 10 5天时间的循环------------------
    # ----- 新增 15 25 35 40 45 50 55
    # 以 5 天为例子
    policy_day = 55
    # 获取时间 和对应序列
    total_time = df_combine.index.strftime('%Y-%m-%d')
    total_time = total_time[:3729]  # 时间序列
    df_all = pd.DataFrame(columns=['bkdm', 'zf', 'cjl', 'cje', 'industry_name', 'score', 'time'])
    # 这是需要计算的所有天数

    for i in range(policy_day - 1, len(total_time)):
        # for i in range(3728, len(total_time)):
        print("[%d / %d] " % (i, len(total_time) - 1))
        # 进入循环的日期
        temp_time_list = []
        for i_day in range(i - (policy_day - 1), i + 1):
            temp_time_list.append(total_time[i_day])

        # ---------------- 前n天 打分功能  --------------
        df_res = df_combine
        #  时间窗口
        for go_day in temp_time_list:
            df_temp = df_combine[go_day].sort_values(by='zf', axis=0, ascending=False)  # 涨幅由大到小
            # 记分
            df_temp = df_temp.head(30)
            df_temp['rank'] = range(len(df_temp))
            df_temp['rank'] = df_temp['rank'] + 1
            df_temp = df_temp.drop(labels=['zf', 'cjl', 'cje', 'score', 'industry_name'], axis=1)
            df_res = pd.merge(df_res, df_temp, how='left', on=['time', 'bkdm'])
            # 得到 某天的排名，计分
            df_res.fillna(0, inplace=True)  # Nan 替换成 0
            df_res['score'] = df_res['score'] + df_res['rank']
            df_res = df_res.drop(labels=['rank'], axis=1)
            # 转 Int
            df_res['score'] = df_res['score'].astype(np.int64)
            # 输出 首先分数不为 0 得分升序排列的数字
        # 检查 2020-09-28 当天的排序结果
        # print(df_res.query('time == "2020-09-28"').sort_values(by='zf', axis=0, ascending=False).head(10))
        grouped_sum = df_res.groupby('bkdm').score.sum().reset_index()
        grouped_sum['time'] = temp_time_list[policy_day - 1]  # 给定时间
        grouped_sum['time'] = pd.to_datetime(grouped_sum['time'], format='%Y-%m-%d')  # 格式转换
        # 结果得分 和 res 对应 代码 和 时间 结合记录！！！
        # print(df_res.query('score != 0').sort_values(by='score', axis=0, ascending=True))
        # 暂存数据
        df_comb = pd.merge(df_combine, grouped_sum, how='right', on=['time', 'bkdm'])
        # print(df_bksj)  存放 N 日 的结果
        df_comb['score_x'] = df_comb['score_y']
        df_comb = df_comb.drop(labels=['score_y'], axis=1)
        df_comb.rename(columns={'score_x': 'score'}, inplace=True)
        df_comb['sj'] = df_comb['time']
        # sj 转为 索引
        df_comb.set_index(['sj'], inplace=True)
        # Nan 替换成 0
        df_comb.fillna(0, inplace=True)
        df_comb['score'] = df_comb['score'].astype(np.int64)
        # 最后的 总排序
        df_all = df_all.append(df_comb.query('score != 0').sort_values(by='score', axis=0, ascending=True))
        # df_all.to_csv('policy1_' + str(policy_day) + 'day.csv', index=False)
    # 最终结果 policy_day 对policy_day 修改计算不同时间下的数据
    df_all.to_csv('policy1_' + str(policy_day) + 'day.csv', index=False)


# 排名积分改为按需 排名
def policy1_process():
    policy_days = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60]
    count = 0
    for policy_day in policy_days:
        df_all = pd.DataFrame(columns=['bkdm', 'zf', 'cjl', 'cje', 'industry_name', 'score', 'time', 'rank'])
        df_policy1_15 = pd.read_csv('policy1_' + str(policy_day) + 'day.csv', encoding="utf-8")
        # 取出时间
        df_time = df_policy1_15['time'].unique()
        # print(df_policy1_15.head(10))
        # 保留time 关联
        df_policy1_15['sj'] = df_policy1_15['time']
        # sj 转为 索引
        df_policy1_15.set_index(['sj'], inplace=True)
        # print(df_policy1_15.head(10))
        # first_day = '2005-06-27'
        # count = 0
        for day in df_time:
            df_temp = df_policy1_15[day:day].sort_values(by='score', axis=0)  # 升序
            df_temp['rank'] = range(len(df_temp))
            df_temp['rank'] = df_temp['rank'] + 1
            # print(df_temp.head(10))
            df_all = df_all.append(df_temp)
            # print("[%d / %d] " % (count, len(df_time) - 1))
            # count = count + 1
        df_all = df_all.drop(labels=['score'], axis=1)
        # 排名替换分数
        df_all.to_csv('policy1_' + str(policy_day) + 'day_process.csv', index=False)
        print("[%d / %d] " % (count, len(policy_days) - 1))
        count = count + 1


# 临时表处理 把分数替换排名
def temp_daily():
    temp_table = pd.read_csv('D:/game/temp_daily2.csv', encoding="utf-8")
    temp_table['trade_date'] = pd.to_datetime(temp_table['trade_date'], format='%Y/%m/%d')
    temp_table['trade_date'] = temp_table['trade_date'].apply(lambda x: x.strftime('%Y-%m-%d'))
    # print(temp_table.head(10))
    policy_final = pd.read_csv('policy_final_process.csv', encoding="utf-8")
    # pd.set_option('display.max_columns', None)
    policy_final = policy_final.drop(labels=['open', 'high', 'low', 'close', 'vol', 'amount',
                                             "换手率（%）", "换手率（自由流通股）", "量比", "市盈率（总市值/净利润， 亏损的PE为空）", "市盈率（TTM，亏损的PE为空）",
                                             "市净率（总市值/净资产）", "市销率", "市销率（TTM）", "股息率 （%）", "股息率（TTM）（%）",
                                             "总股本 （万股）", "流通股本 （万股）", "自由流通股本 （万）", "总市值 （万元）",
                                             "流通市值（万元）", 'ma5', 'ma10', 'ma20', 'ma30', 'ma60', 'ma120', 'ma250', 'kdj_K', 'kdj_D', 'kdj_J',
                                             'fivedayhs','updown_rate', 'BBI1', 'BBI2', 'BBI3', 'name', 'industry_id'
                                             ], axis=1)

    # print(policy_final.head(10))
    df_end = pd.merge(temp_table, policy_final, how='left',
                      left_on=['ts_code', 'trade_date'], right_on=['ts_code', 'trade_date'])
    df_end.to_csv('policy_final_TempProcess.csv', index=False)



'''
策略二：  降序排序
    在前 N 天之内，每日前六名的板块出现的次数，计一分，最后对分数进行累加，由高到低进行排序
    分数相同按照市值进行排序(后处理)
'''


def policy_2():
    # 读取
    # 板块排名
    df_bksj = pd.read_csv("D:/硕士研究/毕业设计准备/股票代码及处理/模块排序处理/model_info.csv", encoding="utf-8")
    # 数据过大，取煤炭板块 demo尝试
    df_bksj_demo = pd.read_csv("D:/硕士研究/毕业设计准备/股票代码及处理/模块排序处理/model_info_demo.csv", encoding="utf-8")

    # 板块 细分信息
    df_industry = pd.read_csv("D:/硕士研究/毕业设计准备/股票代码及处理/模块排序处理/industry_info.csv", encoding="utf-8")
    df_industry = df_industry.drop(labels=['parent_id'], axis=1)
    # pd.set_option('display.max_columns', None)
    # 显示所有的列，不省略

    # 一级板块合并

    df_combine = pd.merge(df_bksj, df_industry, how='inner', left_on='bkdm', right_on='industry_id')
    df_combine = df_combine.drop(labels=['industry_id', 'type'], axis=1)
    # 股票基本信息
    # df_stock_base = pd.read_csv("D:/硕士研究/毕业设计准备/前复权日线+指标(第一次数据)/A股基础信息.csv", encoding="utf-8")

    # pd.set_option('display.max_columns', None)   显示所有的行，不省略

    # 股票日线信息  只要 三个字段，排序总市值最后使用的数据
    # df_daily = pd.read_csv("all_in_one.csv", encoding="utf-8")
    # daily_order = ["ts_code", "trade_date", "总市值 （万元）"]
    # df_daily = df_daily[daily_order]
    # 读取 -------------------------------------------------------

    # 分数列
    df_combine['score'] = 0
    # df_time = df_bksj_demo.query('bkdm==880201')['sj']

    # 转换 时间格式
    df_combine['sj'] = pd.to_datetime(df_combine['sj'], format='%Y%m%d')
    # 保留time 关联
    df_combine['time'] = df_combine['sj']
    # sj 转为 索引
    df_combine.set_index(['sj'], inplace=True)

    # -----------------进入60 30 20 10 5天时间的循环------------------
    # 以 5 天为例子
    policy_day = 60
    # 获取时间 和对应序列
    total_time = df_combine.index.strftime('%Y-%m-%d')
    total_time = total_time[:3729]  # 时间序列
    df_all = pd.DataFrame(columns=['bkdm', 'zf', 'cjl', 'cje', 'industry_name', 'score', 'time'])
    # 这是需要计算的所有天数
    for i in range(policy_day - 1, len(total_time)):
        # for i in range(3728, len(total_time)):
        # 测试用例 2020-09-28
        print("[%d / %d] " % (i, len(total_time) - 1))
        # 进入循环的日期
        temp_time_list = []
        for i_day in range(i - (policy_day - 1), i + 1):
            temp_time_list.append(total_time[i_day])

        # ---------------- 前n天 打分功能  --------------
        df_res = df_combine
        #  时间窗口
        for go_day in temp_time_list:
            df_temp = df_combine[go_day].sort_values(by='zf', axis=0, ascending=False)  # 涨幅由大到小
            # 记分
            df_temp = df_temp.head(6)
            df_temp['rank'] = 1
            df_temp = df_temp.drop(labels=['zf', 'cjl', 'cje', 'score', 'industry_name'], axis=1)

            df_res = pd.merge(df_res, df_temp, how='left', on=['time', 'bkdm'])

            # 得到 某天的排名，计分
            df_res.fillna(0, inplace=True)  # Nan 替换成 0
            df_res['score'] = df_res['score'] + df_res['rank']
            df_res = df_res.drop(labels=['rank'], axis=1)
            # 转 Int
            df_res['score'] = df_res['score'].astype(np.int64)
            # 输出 首先分数不为 0 得分升序排列的数字
        # 检查一个时间周期的得分
        # print(df_res.query('score != 0').sort_values(by='score', axis=0, ascending=True))

        # 检查 2020-09-28 当天的排序结果
        # print(df_res.query('time == "2020-09-28"').sort_values(by='zf', axis=0, ascending=False).head(10))

        # group 对象 保存为 df
        grouped_sum = df_res.groupby('bkdm').score.sum().reset_index()
        grouped_sum['time'] = temp_time_list[policy_day - 1]  # 给定时间
        grouped_sum['time'] = pd.to_datetime(grouped_sum['time'], format='%Y-%m-%d')  # 格式转换

        # 结果得分 和 res 对应 代码 和 时间 结合记录！！！
        # print(df_res.query('score != 0').sort_values(by='score', axis=0, ascending=True))

        # 暂存数据
        df_comb = pd.merge(df_combine, grouped_sum, how='right', on=['time', 'bkdm'])
        # print(df_bksj)  存放 N 日 的结果
        df_comb['score_x'] = df_comb['score_y']
        df_comb = df_comb.drop(labels=['score_y'], axis=1)
        df_comb.rename(columns={'score_x': 'score'}, inplace=True)
        df_comb['sj'] = df_comb['time']
        # sj 转为 索引
        df_comb.set_index(['sj'], inplace=True)
        # Nan 替换成 0
        df_comb.fillna(0, inplace=True)
        df_comb['score'] = df_comb['score'].astype(np.int64)
        # 最后的 总排序
        df_all = df_all.append(df_comb.query('score != 0').sort_values(by='score', axis=0, ascending=False))
        # print(df_all)
        # df_all.to_csv('policy2_' + str(policy_day) + 'day.csv', index=False)

    # 最终结果
    # print(df_bksj.query('score != 0').sort_values(by='score', axis=0, ascending=True))
    # df_bksj['score'].replace(0, np.nan, inplace=True)
    df_all.to_csv('policy2_' + str(policy_day) + 'day.csv', index=False)


if __name__ == '__main__':
    # policy1_score()
    # policy_2()
    temp_daily()
